package com.wen.tian.shiro.config;

import com.wen.tian.shiro.filter.KickoutSessionFilter;
import com.wen.tian.shiro.realm.CustormerRealm;
import com.wen.tian.utils.StringUtils;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

/**
 * shiro配置类
 *
 * @author tww
 * ClassName: ShiroConfig.java、
 * createTime: 2021年01月02日 13:10:48
 **/
@Configuration
public class ShiroConfig {

    private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);

    // Session超时时间，单位为毫秒（默认30分钟）
    @Value("${shiro.session.expireTime}")
    private int expireTime;

    /**
     * 创建shiroFilter 负责拦截所有请求
     *
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        logger.info("拦截所有请求shiroFilter");

        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

        //设置安全管理器
        factoryBean.setSecurityManager(securityManager);

        //配置受限和公共资源
        LinkedHashMap<String, String> map = new LinkedHashMap<>();

        map.put("/**/js/**", "anon");
        map.put("/**/css/**", "anon");
        map.put("/**/img/**", "anon");
        map.put("/**/404.html", "anon");
        map.put("/**/500.html", "anon");
        map.put("/login", "anon");
        map.put("/**", "authc");
        factoryBean.setLoginUrl("/login");
        factoryBean.setSuccessUrl("/index");
        factoryBean.setUnauthorizedUrl("/unauthor");
        factoryBean.setFilterChainDefinitionMap(map);

        return factoryBean;
    }

    /**
     * 安全管理器
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager(Realm realm) {
        logger.info("设置安全管理器");
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //给安全管理器赋值一个realm,声明使用哪个realm
        securityManager.setRealm(realm);
        return securityManager;
    }

    /**
     * 自定义Realm
     */
    @Bean
    public Realm getRealm() {
        logger.info("自定义realm");
        CustormerRealm custormerRealm = new CustormerRealm();
        return custormerRealm;
    }


    /**
     * 会话管理器
     */
    @Bean
    public DefaultWebSessionManager defaultWebSessionManager() {
        DefaultWebSessionManager manager = new DefaultWebSessionManager();
        // 加入缓存管理器
        manager.setCacheManager(getEhCacheManager());
        // 删除过期的session
        manager.setDeleteInvalidSessions(true);
        // 设置全局session超时时间
        manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
        // 去掉 JSESSIONID
        manager.setSessionIdUrlRewritingEnabled(false);
        // 是否定时检查session
        manager.setSessionValidationSchedulerEnabled(true);
        // 自定义SessionDao
        manager.setSessionDAO(sessionDAO());
        // 自定义sessionFactory
        manager.setSessionFactory(sessionFactory());
        return manager;
    }

    /**
     * 缓存管理器 使用Ehcache实现
     */
    @Bean
    public EhCacheManager getEhCacheManager() {
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");
        return cacheManager;
    }

    /**
     * 同一个用户多设备登录限制
     */
    public KickoutSessionFilter kickoutSessionFilter() {
        KickoutSessionFilter kickoutSessionFilter = new KickoutSessionFilter();
        kickoutSessionFilter.setCacheManager(getEhCacheManager());
        kickoutSessionFilter.setSessionManager(defaultWebSessionManager());
        // 同一个用户最大的会话数，默认-1无限制；比如2的意思是同一个用户允许最多同时两个人登录
        kickoutSessionFilter.setMaxSession(maxSession);
        // 是否踢出后来登录的，默认是false；即后者登录的用户踢出前者登录的用户；踢出顺序
        kickoutSessionFilter.setKickoutAfter(kickoutAfter);
        // 被踢出后重定向到的地址；
        kickoutSessionFilter.setKickoutUrl("/login?kickout=1");
        return kickoutSessionFilter;
    }


}
